package org.jsets.fastboot.security.online;

import java.util.Optional;
import java.util.Set;
import org.jsets.fastboot.security.cache.Cache;
import org.jsets.fastboot.security.cache.ICacheManager;
import org.jsets.fastboot.security.config.SecurityProperties;
import org.jsets.fastboot.security.token.ITokenManager;
import org.jsets.fastboot.security.token.TokenStub;
import com.google.common.collect.Sets;

public class OnlineManager {

	private final SecurityProperties properties;
	private final ITokenManager tokenManager;
	private final Cache cache;

	public OnlineManager(SecurityProperties properties, ICacheManager cacheManager, ITokenManager tokenManager) {
		this.properties = properties;
		this.tokenManager = tokenManager;
		this.cache = cacheManager.create(properties.getUserOnlineCacheName());
	}

	public void online(TokenStub tokenStub) {
		this.cache.put(tokenStub.getUsername(), tokenStub.getId());
	}

	public boolean isOnline(String username) {
		Optional<String> stubId = this.cache.getAs(username, String.class);
		if (!stubId.isPresent()) {
			return false;
		}
		
		Optional<TokenStub> stub = this.tokenManager.getTokenStub(stubId.get());
		if (stub.isPresent()) {
			return true;
		}
		
		this.cache.delete(username);
		return false;
	}

	public Optional<TokenStub> getOnlineTokenStub(String username) {
		Optional<String> stubId = this.cache.getAs(username, String.class);
		if (!stubId.isPresent()) {
			return Optional.empty();
		}
		
		Optional<TokenStub> stub = this.tokenManager.getTokenStub(stubId.get());
		return stub;
	}

	public Set<String> getOnlineUserList() {
		Set<String> onlines = Sets.newHashSet();
		Set<String> usernames = this.cache.getKeys();
		for (String username : usernames) {
			Optional<String> stubId = this.cache.getAs(username, String.class);
			if (stubId.isPresent() && this.tokenManager.getTokenStub(stubId.get()).isPresent()) {
				onlines.add(username);
			}else {
				this.cache.delete(username);
			}
		}
		return onlines;
	}

	public void forceLogout(String username, String cause) {
		Optional<String> stubId = this.cache.getAs(username, String.class);
		if (!stubId.isPresent()) {
			return;
		}
		
		this.tokenManager.removeTokenStub(stubId.get());
	}

}